#ifndef PARSEDATA_H
#define PARSEDATA_H
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <cmath>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <lcm/lcm-cpp.hpp>
#include <string>
#include <vector>
#include "buffer_data_t.hpp"
#include "gga_t.hpp"
#include "gnss_initial_t.hpp"
#include "gps_imu_info_t.hpp"
#include "imu_t.hpp"
#include "vehicle_status_t.hpp"
#include <fstream>
#include <list>

#ifdef _MSC_VER
#include <windows.h>

#define _USE_MATH_DEFINES

inline int gettimeofday(struct timeval* tp, void* tzp) {
  unsigned long t;
  t = timeGetTime();
  tp->tv_sec = t / 1000;
  tp->tv_usec = t % 1000;
  return 0;
}
#else  // _MSC_VER
#include <sys/time.h>
#endif  // _MSC_VER

static inline unsigned long GetCurrentTimeInMilliSec() {
  static unsigned long milliseconds;
#ifdef _MSC_VER
  SYSTEMTIME stime;
  GetSystemTime(&stime);
  milliseconds =
      ((stime.wHour * 60 + stime.wMinute) * 60 + stime.wSecond) * 1000 +
      stime.wMilliseconds;
#else
  static struct timeval tv;
  gettimeofday(&tv, NULL);
  milliseconds = (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
#endif
  return milliseconds;
}
using namespace std;
#pragma pack(push, 1)
typedef struct {
  int8_t AA;                  // 0
  int8_t BB;                  // 1
  int8_t data_out;            // 2
  int8_t data_type;           // 3
  int16_t data_len;           // 4
  int16_t yaw;                // 6
  int16_t pitch;              // 8
  int16_t roll;               // 10
  int16_t v_x;                // 12
  int16_t v_y;                // 14
  int16_t v_z;                // 16
  int16_t accX;               // 18
  int16_t accY;               // 20
  int16_t accZ;               // 22
  int16_t c_x;                // 24
  int16_t c_y;                // 26
  int16_t c_z;                // 28
  int16_t zj;                 // 30
  int16_t yun_fang;           // 32
  int16_t t;                  // 34
  int32_t lat;                // 36
  int32_t lon;                // 40
  int32_t altitude;           // 44
  int32_t V_north;            // 48
  int32_t V_east;             // 52
  int32_t V_tianxian;         // 56
  int32_t gnss_lan;           // 60
  int32_t gnss_lon;           // 64
  int32_t gnss_h;             // 68
  int32_t gnss_v;             // 72
  int16_t gnss_angle;         // 76
  int32_t gnss_tian_v;        // 78
  uint32_t time;              // 82
  int8_t gnss1;               // 86  88
  int8_t gnss2;               // 87
  int8_t StarNum;             // 88
  int16_t v_delay;            // 89
  int8_t localization;        // 91
  int16_t gnss_yaw;           // 92
  uint16_t yaw_delay;         // 94
  uint16_t pose_delay;        // 96
  uint16_t speed_delay;       // 98
  int16_t pressure;           // 100
  int32_t pressure_altitude;  // 102
  int8_t gps_updata;          // 106
  int32_t check_sum;          // 107

} INS_D;
extern INS_D ins_d;
#pragma pack(pop)
typedef struct {
  float acclat_ins;
  float acclon_ins;
  float acclat;
  float acclon;
  float steerangle;
  float yawrate;
  float speL;
  float speR;
  float DisL;
  float DisR;
} Vehiclestatus;
extern Vehiclestatus vehicle_status;

typedef struct {
  double Lat;  // gga
  double Lon;
  double high;
  int statu;
  int StarNum;
  double HDOP;
  double Speed;
  double Heading;
  int AltitudeStu;
  double lat_ini;  // ins
  double lon_ini;
  double alt_ini;
  double ve;
  double vn;
  double vd;
  double yaw;
  double pitch;
  double roll;
  double velocity;
  float ax;
  float ay;
  float az;
  float gx;
  float gy;
  float gz;

  double latE;  // dr
  double lonE;
  double headingE;
  double confidence;
  int tszt;
  int tsflag;
  int laser_jz;
  double X_dev_x;
  double X_dev_y;
  double x_dev;
  string insStatu;
  string INS_statu;
  vector<u_int8_t> ins_statu;
  float tmpe;
  float time;
  vector<u_int8_t> datatype;
  string ins_type = "cpt";
  string strGGA;

  float yaw_c=0.0;
} GPS_INI;
extern GPS_INI gps_ini;

#pragma pack(push, 1)
typedef struct {
  char A;
  char B;
  char C;
  int16_t roll;
  int16_t pitch;
  int16_t azimuth;
  int16_t gyroscope_x;
  int16_t gyroscope_y;
  int16_t gyroscope_z;
  int16_t accX;
  int16_t accY;
  int16_t accZ;
  int32_t lat;
  int32_t lon;
  int32_t altitude;

  int16_t V_north;
  int16_t V_east;
  int16_t V_ground;
  int8_t state;
  char Retain[6];
  int16_t data0;
  int16_t data1;
  int16_t data2;
  uint32_t time;
  uint8_t data_type;
  uint8_t check;
  bool is_daoyuan;
  bool status;
  bool wheelspeed;
  float yawPrecision;
  float localizationPrecesion;
  float vectoryPrecesion;
  float tempreture;
  uint16_t GPSstute;
  uint16_t GPSNUM;
  uint16_t yawStute;

} daoyuan_imu;
extern daoyuan_imu DaoYuan_imu;
#pragma pack(pop)

typedef struct {
  float gAngle;
  float gRate;
  float accX;
  float accY;
  float accZ;
  float gyroscope_x;
  float gyroscope_y;
  float gyroscope_z;

  float yaw;
  float pitch;
  float roll;
} imu;
extern imu IMU;

typedef enum cpt_status {
  INS_INACTIVE = 0,
  INS_ALIGNING = 1,
  INS_HIGH_VARIANCE = 2,
  INS_SOLUTION_GOOD = 3,
  INS_SOLUTION_FREE = 6,
  INS_ALIGNMENT_COMPLETE = 7,
  DETERMINING_ORIENTATION = 8,
  WAITING_INITIALPOS = 9
} Cpt_Status;
#pragma pack(push, 1)
typedef struct {
  u_int32_t week;
  double seconds;
  double latitude;
  double longitude;
  double altitude;
  double northVelocity;
  double eastVelocity;
  double upVelocity;
  double roll;
  double pitch;
  double azimuth;
  u_int32_t  cpt_status;
  u_int32_t crc;
  float Z_Accuracy;
   long utime;



} CPT;
extern CPT CPT_imu;

#pragma pack(pop)

#pragma pack(pop)
class ParseData {
 public:
  ParseData();

 public:
  lcm::LCM* LCM_;
  bool m_bSysTime;
  long m_lCurTime;
  long imu_lasttime=0;
 ofstream m_fSave;
  string m_strSaveFilePath;
  void SysTime();

  void handleMessage(const lcm::ReceiveBuffer* rbuf, const std::string& chan,
                     const lcmtypes::vehicle_status_t* msg);

  void ggaMessage(const lcm::ReceiveBuffer* rbuf, const std::string& chan,
                  const lcmtypes::buffer_data_t* msg);

  void gnssMessage(const lcm::ReceiveBuffer* rbuf, const std::string& chan,
                   const lcmtypes::buffer_data_t* msg);
  void imuMessage(const lcm::ReceiveBuffer* rbuf, const std::string& chan,
                  const lcmtypes::buffer_data_t* msg);

  bool gpsParse(vector<u_int8_t>);

  bool XWgpsParse(vector<u_int8_t>);
  bool parse_data(vector<u_int8_t>);
  bool ljlparse_data(vector<u_int8_t>& , list<CPT>&);
  bool ljlparse_data(std::vector<u_int8_t> &imu_strRecv,ofstream &);
  bool parse_daoyuan_data(vector<u_int8_t>);
  bool parse_ins_d_data(vector<u_int8_t>);
  bool parse_imudata(vector<u_int8_t>);
  bool parse_imu3_data(vector<u_int8_t>);
  void SplitString(const string& s, vector<string>& v, const string& c);
};

#endif  // PARSEDATA_H
